#include "StdAfx.h"
#include "FlowConditionNode.h"

void CFlowNode_Condition::GetConfiguration( SFlowNodeConfig &config )
{
	static const SInputPortConfig in_config[] = {
		InputPortConfig<bool>( "condition", _HELP("Setting this input to TRUE sends the value [value] to the [true] port, otherwise to [false]") ),
		InputPortConfig_AnyType( "value", _HELP("Value to direct to a true or false port") ),
		InputPortConfig_Null()
	};
	static const SOutputPortConfig out_config[] = {
		OutputPortConfig_AnyType( "true", _HELP("Activated when the condition is true (passes the value through)") ),
		OutputPortConfig_AnyType( "false", _HELP("Activated when the condition is false (passes the value through)") ),
		OutputPortConfig_Null()
	};
	config.sDescription = _HELP("LEGACY! Node to route data flow based on a boolean condition. Both inputs trigger the output.\nLegacy. Use Logic:Condition instead!");
	config.pInputPorts = in_config;
	config.pOutputPorts = out_config;
	config.SetCategory(EFLN_APPROVED);
}

void CFlowNode_Condition::ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo )
{
	switch (event)
	{
	case eFE_Activate:
	case eFE_Initialize:
		bool bCondition = GetPortBool(pActInfo, 0);

		if (bCondition)
			ActivateOutput( pActInfo, 0, GetPortAny(pActInfo, 1));
		else
			ActivateOutput( pActInfo, 1, GetPortAny(pActInfo, 1));
	};
};


class CFlowNode_LogicCondition : public CFlowBaseNode<eNCT_Singleton>
{
public:
	CFlowNode_LogicCondition( SActivationInfo * ) {}

	void GetConfiguration( SFlowNodeConfig &config )
	{
		static const SInputPortConfig in_config[] = {
			InputPortConfig<bool>  ( "Condition", _HELP("If condition is FALSE input [In] will be routed to [OnFalse], otherwise to [OnTrue]") ),
			InputPortConfig_AnyType( "In",        _HELP("Value to route to [OnFalse] or [OnTrue], based on [Condition]") ),
			InputPortConfig_Null()
		};
		static const SOutputPortConfig out_config[] = {
			OutputPortConfig_AnyType( "OnFalse", _HELP("Set to input [In] if [Condition] is FALSE)") ),
			OutputPortConfig_AnyType( "OnTrue",  _HELP("Set to input [In] if [Condition] is TRUE") ),
			OutputPortConfig_Null()
		};
		config.sDescription = _HELP("Node to route data flow based on a boolean condition.\nSetting input [Value] will route it either to [OnFalse] or [OnTrue].");
		config.pInputPorts = in_config;
		config.pOutputPorts = out_config;
		config.SetCategory(EFLN_APPROVED);

	}

	virtual void GetMemoryUsage(ICrySizer * s) const
	{
		s->Add(*this);
	}

	void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo )
	{
		switch (event)
		{
		case eFE_Activate:
			// only port 1 [In] triggers an output
			if (IsPortActive(pActInfo, 1) == false)
				return;

			const bool bCondition = GetPortBool(pActInfo, 0);

			if (bCondition == false)
				ActivateOutput( pActInfo, 0, GetPortAny(pActInfo, 1));
			else
				ActivateOutput( pActInfo, 1, GetPortAny(pActInfo, 1));
		};
	}
};


class CFlowNode_LogicConditionInverse : public CFlowBaseNode<eNCT_Singleton>
{
	enum EInputs
	{
		IN_CONDITION = 0,
		IN_TRUE,
		IN_FALSE,
	};

public:
	CFlowNode_LogicConditionInverse( SActivationInfo * ) {}

	void GetConfiguration( SFlowNodeConfig &config )
	{
		static const SInputPortConfig in_config[] = {
			InputPortConfig<bool>  ( "Condition", _HELP("If condition is FALSE input [False] will be routed to output, otherwise input [True] will be") ),
			InputPortConfig_AnyType( "True",			_HELP("value to redirect to output when [Condition] is TRUE)") ),
			InputPortConfig_AnyType( "False",			_HELP("value to redirect to output when [Condition] is FALSE)") ),
			InputPortConfig_Null()
		};
		static const SOutputPortConfig out_config[] = {
			OutputPortConfig_AnyType( "Out",     _HELP("Value to output from [False] or [True], based on [Condition]") ),
			OutputPortConfig_Null()
		};
		config.sDescription = _HELP("Node to route data flow based on a boolean condition.\nDepending on [Condition], either input [True] or [False] will be redirected to [out].");
		config.pInputPorts = in_config;
		config.pOutputPorts = out_config;
		config.SetCategory(EFLN_APPROVED);

	}

	virtual void GetMemoryUsage(ICrySizer * s) const
	{
		s->Add(*this);
	}

	void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo )
	{
		if (event==eFE_Activate)
		{
			bool bCondition = GetPortBool(pActInfo, IN_CONDITION);
		
			if (bCondition)
			{
				if (IsPortActive(pActInfo, IN_TRUE))
					ActivateOutput( pActInfo, 0, GetPortAny(pActInfo, IN_TRUE));
			}
			else
			{
				if (IsPortActive(pActInfo, IN_FALSE))
					ActivateOutput( pActInfo, 0, GetPortAny(pActInfo, IN_FALSE));
			}
		}
	}
};


REGISTER_FLOW_NODE( "Condition",CFlowNode_Condition)
REGISTER_FLOW_NODE( "Logic:Condition",CFlowNode_LogicCondition)
REGISTER_FLOW_NODE( "Logic:ConditionInverse",CFlowNode_LogicConditionInverse)
